import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from collections import Counter
import re

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 读取历史开奖数据
try:
    df = pd.read_excel("zhongjiang.xlsx")
    print(f"成功读取 {len(df)} 期开奖数据")
    print(f"数据时间段: {df['开奖日期'].min()} 至 {df['开奖日期'].max()}")
except Exception as e:
    print(f"读取数据文件失败: {e}")
    exit()

# 数据检查：验证开奖期数和数据量
if '前区号码' not in df.columns or '后区号码' not in df.columns:
    print("数据文件缺少必要的列名: '前区号码' 或 '后区号码'")
    exit()


# 提取前后区号码并统计每个数字的出现次数
def extract_numbers(df, column_name, max_num):
    """提取单个数字并统计频率"""
    # 创建所有可能数字的列表（01到max_num）
    all_numbers = [f"{i:02d}" for i in range(1, max_num + 1)]
    counter = Counter()

    # 遍历每一期的号码
    for numbers_str in df[column_name].dropna():
        # 使用正则表达式提取所有两位数的数字
        numbers_list = re.findall(r'\d{2}', numbers_str)

        # 确保提取到的数字数量正确
        expected_count = 5 if column_name == "前区号码" else 2
        if len(numbers_list) != expected_count:
            print(
                f"警告: 第 {df[df[column_name] == numbers_str].index[0]} 行提取到 {len(numbers_list)} 个{column_name}号码，应为 {expected_count} 个")

        # 统计每个数字
        for num in numbers_list:
            if num in all_numbers:
                counter[num] += 1
            else:
                print(f"警告: 发现无效号码 '{num}'，在 '{numbers_str}' 中")

    # 确保所有可能的数字都有计数（即使为0）
    for num in all_numbers:
        if num not in counter:
            counter[num] = 0

    # 转换为DataFrame并排序
    df_result = pd.DataFrame(counter.items(), columns=["数字", "出现次数"])
    df_result = df_result.sort_values("数字")
    return df_result


# 统计前区和后区数字
front_df = extract_numbers(df, "前区号码", 35)
back_df = extract_numbers(df, "后区号码", 12)

# 验证统计结果是否正确
expected_front_count = len(df) * 5  # 前区每期5个数字
expected_back_count = len(df) * 2  # 后区每期2个数字

actual_front_count = front_df["出现次数"].sum()
actual_back_count = back_df["出现次数"].sum()


if actual_front_count != expected_front_count:
    print(f"警告: 前区数字总出现次数({actual_front_count})不等于期数×5({expected_front_count})")

if actual_back_count != expected_back_count:
    print(f"警告: 后区数字总出现次数({actual_back_count})不等于期数×2({expected_back_count})")

# 数据检查：验证频率统计
print("\n前区数字频率统计:")
print(front_df)
print("\n后区数字频率统计:")
print(back_df)

# 创建前区图表
plt.figure(figsize=(18, 8))
plt.bar(front_df["数字"], front_df["出现次数"], color='skyblue')
plt.title(f"前区数字出现频率 ({len(df)}期数据)", fontsize=16)
plt.xlabel("前区数字 (01-35)", fontsize=14)
plt.ylabel("出现次数", fontsize=14)
plt.xticks(rotation=45, fontsize=10)
for i, value in enumerate(front_df["出现次数"]):
    plt.text(i, value + 0.1, str(value), ha='center', va='bottom', fontsize=9)
plt.tight_layout()
plt.savefig("front_digit_frequency.png", dpi=300, bbox_inches='tight')
plt.show()

# 创建后区图表
plt.figure(figsize=(12, 6))
plt.bar(back_df["数字"], back_df["出现次数"], color='salmon')
plt.title(f"后区数字出现频率 ({len(df)}期数据)", fontsize=16)
plt.xlabel("后区数字 (01-12)", fontsize=14)
plt.ylabel("出现次数", fontsize=14)
plt.xticks(fontsize=11)
for i, value in enumerate(back_df["出现次数"]):
    plt.text(i, value + 0.1, str(value), ha='center', va='bottom', fontsize=10)
plt.tight_layout()
plt.savefig("back_digit_frequency.png", dpi=300, bbox_inches='tight')
plt.show()

# 基于频率分析的推荐
print("\n基于数字频率分析的推荐投注号码:")


def generate_recommendation(freq_df, num_select, zone_name):
    weights = np.array(freq_df['出现次数']) + 1  # 加1避免概率为0
    selected = np.random.choice(
        freq_df['数字'],
        size=num_select,
        replace=False,
        p=weights / weights.sum()
    )
    return sorted([int(d) for d in selected])


front_recommend = generate_recommendation(front_df, 5, "前区")
back_recommend = generate_recommendation(back_df, 2, "后区")
print("前区：", ", ".join(f"{x:02}" for x in front_recommend))
print("后区：", ", ".join(f"{x:02}" for x in back_recommend))